package cn.itcast.service.impl;

import cn.itcast.service.ReportService;
import cn.itheima.feign.OrderClient;
import cn.itheima.feign.UserClient;
import cn.itheima.orders.pojo.Orders;
import cn.itheima.orders.vo.OrderReportVO;
import cn.itheima.sys.vo.BusinessDataVO;
import cn.itheima.sys.vo.SalesTop10ReportVO;
import cn.itheima.sys.vo.TurnoverReportVO;
import cn.itheima.users.vo.UserReportVO;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
@AllArgsConstructor
public class ReportServiceImpl implements ReportService {

    private OrderClient orderClient;
    private UserClient userClient;


    /**
     * 营业额数据统计
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return 营业额数据
     */
    @Override
    public TurnoverReportVO getTurnover(LocalDate begin, LocalDate end) {

        List<TurnoverReportVO> list = orderClient.getSumByDate(begin, end);

        return TurnoverReportVO.builder().turnoverList(list.stream().map(TurnoverReportVO::getTurnoverList).collect(Collectors.joining(", "))).dateList(list.stream().map(TurnoverReportVO::getDateList).collect(Collectors.joining(", "))).build();
    }

    /**
     * 用户数据统计
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return 用户数据
     */
    @Override
    public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
        List<UserReportVO> userList = userClient.countByTime(begin, end);

        return UserReportVO.builder().dateList(userList.stream().map(UserReportVO::getDateList).collect(Collectors.joining(", "))).newUserList(userList.stream().map(UserReportVO::getNewUserList).collect(Collectors.joining(", "))).totalUserList(userList.stream().map(UserReportVO::getTotalUserList).collect(Collectors.joining(", "))).build();
    }

    /**
     * 订单统计
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return OrderReportVO
     */
    @Override
    public OrderReportVO getOrdersStatistics(LocalDate begin, LocalDate end) {

        List<LocalDate> dateList = new ArrayList<>();
        List<Integer> validOrderList = new ArrayList<>();
        List<Integer> totalOrderList = new ArrayList<>();

        //2.遍历日期，查询每一天的 有效订单数、订单总数
        while (!begin.isAfter(end)) {
            LocalDateTime startTime = LocalDateTime.of(begin, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(begin, LocalTime.MAX);

            //查询订单总数
            Map<String, Object> map = new HashMap<>();
            map.put("status", Orders.COMPLETED);
            map.put("begin", startTime);
            map.put("end", endTime);
            Integer validOrderCount = orderClient.countByMap(map);

            map.put("status", null);
            Integer totalOrderCount = orderClient.countByMap(map);

            //将数据放入对应的集合中
            dateList.add(begin);
            validOrderList.add(validOrderCount);
            totalOrderList.add(totalOrderCount);

            begin = begin.plusDays(1);
        }


        //拿到validOrderList集合中所有元素的和
        int validOrderCount = validOrderList.stream().mapToInt(i -> i).sum();
        int totalOrderCount = totalOrderList.stream().mapToInt(i -> i).sum();

        //求 订单的完成率
        double orderCompletionRate = totalOrderCount != 0 ? validOrderCount * 1.0 / totalOrderCount : 0;

        return OrderReportVO.builder().dateList(StringUtils.join(dateList, ",")).validOrderCountList(StringUtils.join(validOrderList, ",")).orderCountList(StringUtils.join(totalOrderList, ",")).totalOrderCount(totalOrderCount) //总订单数
                .validOrderCount(validOrderCount) //有效订单数
                .orderCompletionRate(orderCompletionRate) //订单完成率
                .build();

    }

    /**
     * 查询销量排名top10接口
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return OrderReportVO
     */
    @Override
    public SalesTop10ReportVO getTop10(LocalDate begin, LocalDate end) {

        List<SalesTop10ReportVO> top10ReportVOList = orderClient.countDishAndSetmealByTime(begin, end);

        return SalesTop10ReportVO.builder().nameList(top10ReportVOList.stream().map(SalesTop10ReportVO::getNameList).collect(Collectors.joining(", "))).numberList(top10ReportVOList.stream().map(SalesTop10ReportVO::getNumberList).collect(Collectors.joining(", "))).build();
    }

    /**
     * 运营报表统计
     *
     * @param response
     */
    @Override
    @SneakyThrows
    public void exportBusinessData(HttpServletResponse response) {

        InputStream is = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");

        XSSFWorkbook excel = new XSSFWorkbook(is);
        XSSFSheet sheet = excel.getSheetAt(0);

        LocalDate startDate = LocalDate.now().minusMonths(1);
        LocalDate endDate = LocalDate.now().minusDays(1);
        //填充概览数据
        BusinessDataVO businessData = orderClient.getBusinessData(LocalDateTime.of(startDate, LocalTime.MIN), LocalDateTime.of(endDate, LocalTime.MAX));

        sheet.getRow(1).getCell(1).setCellValue(startDate + "至" + endDate);
        sheet.getRow(3).getCell(2).setCellValue(businessData.getTurnover());
        sheet.getRow(3).getCell(4).setCellValue(businessData.getOrderCompletionRate());
        sheet.getRow(3).getCell(6).setCellValue(businessData.getNewUsers());
        sheet.getRow(4).getCell(2).setCellValue(businessData.getValidOrderCount());
        sheet.getRow(4).getCell(4).setCellValue(businessData.getUnitPrice());

        //填充明细数据
        List<BusinessDataVO> businessListData = orderClient.getBusinessListData(LocalDateTime.of(startDate, LocalTime.MIN), LocalDateTime.of(endDate, LocalTime.MAX));

        for (int j = 0; j < businessListData.size(); j++) {
            BusinessDataVO businessDataDetail = businessListData.get(j);
            sheet.getRow(j + 7).getCell(1).setCellValue(startDate.toString());
            sheet.getRow(j + 7).getCell(2).setCellValue(businessDataDetail.getTurnover());
            sheet.getRow(j + 7).getCell(3).setCellValue(businessDataDetail.getValidOrderCount());
            sheet.getRow(j + 7).getCell(4).setCellValue(businessDataDetail.getOrderCompletionRate());
            sheet.getRow(j + 7).getCell(5).setCellValue(businessDataDetail.getUnitPrice());
            sheet.getRow(j + 7).getCell(6).setCellValue(businessDataDetail.getNewUsers());
        }

        excel.write(response.getOutputStream());
        is.close();
        excel.close();
    }
}
